package middle;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
import util.PrintUtils;

public class Solution_341 {

    interface NestedInteger {

          // @return true if this NestedInteger holds a single integer, rather than a nested list.
          public boolean isInteger();

          // @return the single integer that this NestedInteger holds, if it holds a single integer
          // Return null if this NestedInteger holds a nested list
          public Integer getInteger();

          // @return the nested list that this NestedInteger holds, if it holds a nested list
          // Return empty list if this NestedInteger holds a single integer
          public List<NestedInteger> getList();
    }

    static class IntegerC implements NestedInteger {

        private int val;

        public IntegerC(int val) {
            this.val = val;
        }
        @Override
        public boolean isInteger() {
            return true;
        }

        @Override
        public Integer getInteger() {
            return val;
        }

        @Override
        public List<NestedInteger> getList() {
            return null;
        }
    }

    static class ListC implements NestedInteger {

        private List<NestedInteger> list;

        public ListC(List<NestedInteger> list) {
            this.list = list;
        }
        @Override
        public boolean isInteger() {
            return false;
        }

        @Override
        public Integer getInteger() {
            return null;
        }

        @Override
        public List<NestedInteger> getList() {
            return list;
        }
    }

    public static void main(String[] args) {
        List<NestedInteger> nestedList = new ArrayList<>();
//        nestedList.add(new ListC(PrintUtils.newArrayList()));
        nestedList.add(new ListC(PrintUtils.newArrayList(new IntegerC(1), new IntegerC(1))));
        nestedList.add(new IntegerC(2));
        nestedList.add(new ListC(PrintUtils.newArrayList(new IntegerC(1), new IntegerC(1))));
        NestedIterator model = new NestedIterator(nestedList);
        System.out.println(model.hasNext());
        System.out.println(model.next());
        System.out.println(model.hasNext());
        System.out.println(model.next());
        System.out.println(model.hasNext());
        System.out.println(model.next());
        System.out.println(model.hasNext());
        System.out.println(model.next());
        System.out.println(model.hasNext());
        System.out.println(model.next());
        System.out.println(model.hasNext());
    }

    static class NestedIterator implements Iterator<Integer> {

        private int index = 0;
        private List<Integer> list;

        public NestedIterator(List<NestedInteger> nestedList) {
            list = new ArrayList<>();
            dps(nestedList);
        }

        private void dps(List<NestedInteger> nestedList) {
            for (NestedInteger node : nestedList) {
                if (node.isInteger()) {
                    list.add(node.getInteger());
                } else {
                    dps(node.getList());
                }
            }
        }

        @Override
        public Integer next() {
            if (index == list.size()) {
                return null;
            }
            return list.get(index++);
        }

        @Override
        public boolean hasNext() {
            return index < list.size();
        }
    }
}
